package com.fdb.efp.batch.service.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.fdb.basic.framework.core.base.AbstractFrameworkService;
import com.fdb.basic.framework.core.base.FrameworkService;
import com.fdb.basic.framework.core.exception.BizException;
import com.fdb.basic.framework.core.util.DateUtility;
import com.fdb.basic.framework.core.util.SpringContextUtils;
import com.fdb.basic.sequence.service.facade.PatternedLimitableSeqService;
import com.fdb.efp.batch.service.facade.BusCusRelCheckService;
import com.fdb.efp.batch.service.util.SDicMappingUtil;
import com.fdb.efp.cus.service.facade.CusRelCheckService;
import com.fdb.efp.cus.service.facade.CusRelCheckTempService;
import com.fdb.efp.cus.service.vo.CusRelCheckTempVO;
import com.fdb.efp.cus.service.vo.CusRelCheckVO;
import com.fdb.efp.esb.service.bo.req.hlw.ReqAlarmJudgementBean;
import com.fdb.efp.esb.service.bo.resp.hlw.RespAlarmJudgementBean;
import com.fdb.efp.esb.service.facade.hlw.AlarmJudgementService;

@Service("busCusRelCheckService")
public class BusCusRelCheckServiceImpl extends AbstractFrameworkService implements BusCusRelCheckService, FrameworkService {
	private static Logger logger = LoggerFactory.getLogger(BusCusRelCheckServiceImpl.class);

	/** 证件类型 CertType */
	public static final String CERT_TYPE = "CertType";

	@Autowired
	@Qualifier("cusRelCheckService")
	private CusRelCheckService cusRelCheckService;

	@Autowired
	@Qualifier("cusRelCheckTempService")
	private CusRelCheckTempService cusRelCheckTempService;

	@Value("${file.okCusRelCheckDownLoadPath}")
	private String filePath;

	@Value("${file.okCusRelCheckName}")
	private String filename;

	@Autowired
	@Qualifier("alarmJudgementService")
	private AlarmJudgementService alarmJudgementService;

	/**
	 * @description:将人事文件临时表加工到行内员工信息表
	 * @return
	 * @date:2018年12月27日 下午3:23:22
	 * @author:wangyk3
	 */
	@Override
	public Boolean transToCusRelCheck() throws Exception {
		double before = System.currentTimeMillis();
		logger.info("关联人加工任务开始，加工日期：" + DateUtility.getCurrDate());
		// 临时数据列表
		List<CusRelCheckTempVO> cusRelCheckTempVOList = new ArrayList<>();
		// 关联人VO对象
		CusRelCheckVO cusRelCheckVO = null;
		// 关联人VO列表插入对象
		List<CusRelCheckVO> cusRelCheckVOInsertList = null;
		// 关联人VO列表更新对象
		List<CusRelCheckVO> cusRelCheckVOUpdateList = null;
		// 关联人临时表VO对象
		CusRelCheckTempVO cusRelCheckTempVO = null;
		// 总条数
		int sum = 0;
		// 插入条数
		int numInsert = 0;
		// 更新条数
		int numUpdate = 0;
		// 返回标志
		boolean flag = true;
		try {
			cusRelCheckVOInsertList = new ArrayList<>();
			cusRelCheckVOUpdateList = new ArrayList<>();
			// 1.从临时表中查出数据
			cusRelCheckTempVOList = cusRelCheckTempService.queryCusRelCheckTempList();
			sum = cusRelCheckTempVOList.size();
			// 1.1 检查ok文件
			this.okFileCheck(sum);
			// 2.更新到业务表cus_rel_check中
			Iterator<CusRelCheckTempVO> iterator = cusRelCheckTempVOList.iterator();
			while (iterator.hasNext()) {
				// 2.1 获取临时表数据
				cusRelCheckTempVO = iterator.next();
				// 2.2 根据证件号码查询行员信息表
				cusRelCheckVO = cusRelCheckService.queryCusRelCheckBycertCode(cusRelCheckTempVO.getCertCode(),  SDicMappingUtil.getLocalSysDicVal(CERT_TYPE, cusRelCheckTempVO.getCertType()));
				// 2.3 有则更新，无则插入,考虑到数据量不大，暂时不分页
				if (Objects.nonNull(cusRelCheckVO)) {
					cusRelCheckVO.setCusName(cusRelCheckTempVO.getCusName());
					/** 【修改】 @ludayong 2019/02/14  【原语句】cusRelCheckVO.setCertType(cusRelCheckTempVO.getCertType());*/
					String certType = SDicMappingUtil.getLocalSysDicVal(CERT_TYPE, cusRelCheckTempVO.getCertType());
					cusRelCheckVO.setCertType(certType);
					cusRelCheckVO.setCertCode(cusRelCheckTempVO.getCertCode());
					cusRelCheckVO.setRelType(cusRelCheckTempVO.getRelType());
					cusRelCheckVO.setSts(cusRelCheckTempVO.getSts());
					cusRelCheckVOUpdateList.add(cusRelCheckVO);
				} else {
					cusRelCheckVO = new CusRelCheckVO();
					cusRelCheckVO.setRelSerno(this.getCusRelSerno()); // 客户流水号
					cusRelCheckVO.setCusName(cusRelCheckTempVO.getCusName());
					/** 【修改】 @ludayong 2019/02/14  【原语句】cusRelCheckVO.setCertType(cusRelCheckTempVO.getCertType());*/
					String certType = SDicMappingUtil.getLocalSysDicVal(CERT_TYPE, cusRelCheckTempVO.getCertType());
					cusRelCheckVO.setCertType(certType);
					cusRelCheckVO.setCertCode(cusRelCheckTempVO.getCertCode());
					cusRelCheckVO.setRelType(cusRelCheckTempVO.getRelType());
					cusRelCheckVO.setSts(cusRelCheckTempVO.getSts());
					cusRelCheckVO.setRelRelation("01"); // 行员
					cusRelCheckVOInsertList.add(cusRelCheckVO);
				}
			}

			logger.info("****************需要更新条数：【" + cusRelCheckVOUpdateList.size() + "】，需要新增条数：【" + cusRelCheckVOInsertList.size() + "】****************");
			// 2.3 批量插入
			if (cusRelCheckVOInsertList.size() != 0) {
				numInsert = cusRelCheckService.insertCusRelCheckBatch(cusRelCheckVOInsertList);
				if (numInsert < 0) {
					flag = false;
					logger.info("批量新增数据异常！！！！！！");
					throw new Exception("批量新增数据异常！！！！！！");
				}
			}

			// 2.4 批量更新
			if (cusRelCheckVOUpdateList.size() != 0) {
				numUpdate = cusRelCheckService.updateCusRelCheckBatch(cusRelCheckVOUpdateList);
				if (numUpdate < 0) {
					flag = false;
					logger.info("批量更新数据异常！！！！！！");
					throw new Exception("批量更新数据异常！！！！！！");
				}
			}
			double after = System.currentTimeMillis();
			logger.info("耗时[" + (after - before) / 1000 + "]秒");
			logger.info("关联人加工任务结束，加工日期：" + DateUtility.getCurrDate() + " ，总条数：" + sum + " ，新增条数：" + numInsert + " ，更新条数：" + numUpdate);
		} catch (Exception e) {
			logger.error(e.getMessage());
			flag = false;
			/********************/
			// 调用颖风写的告警判断服务
			ReqAlarmJudgementBean reqAlarmJudgementBean = new ReqAlarmJudgementBean();
			reqAlarmJudgementBean.setMonObjNm("网贷批量");
			reqAlarmJudgementBean.setMonObjSpfTpVal("网贷内部");
			reqAlarmJudgementBean.setMonObjLctr(InetAddress.getLocalHost().getHostAddress());
			reqAlarmJudgementBean.setAlrmInf(e.getMessage());
			reqAlarmJudgementBean.setAlrmTmstmp(DateUtility.getCurrAppDateTimeString());
			reqAlarmJudgementBean.setMonAlrmLvl("2");
			RespAlarmJudgementBean respAlarmJudgementBean = alarmJudgementService.alarmJudgement(reqAlarmJudgementBean);
			logger.debug("调用告警判断返回码：【" + respAlarmJudgementBean.getRetCd() + "】，返回信息：【" + respAlarmJudgementBean.getRetMsg() + "】");
			if (Objects.nonNull(respAlarmJudgementBean) && "0000".equals(respAlarmJudgementBean.getRetCd())) {// 调用告警成功
				logger.info("行员文件业务处理告警成功！返回信息码：" + respAlarmJudgementBean.getRetCd());
			} else {
				logger.info("行员文件业务处理告警失败！返回信息码：" + respAlarmJudgementBean.getRetCd());
			}
		}
		return flag;
	}

	/**
	 * @description:获取关系人流水号
	 * @return
	 * @throws Exception
	 * @date:2019年1月8日 下午5:17:55
	 * @author:wangyk3
	 */
	private String getCusRelSerno() throws Exception {
		PatternedLimitableSeqService sequenceService = SpringContextUtils.getBean(PatternedLimitableSeqService.class);
		return sequenceService.getPatternedSequence("CUS_REL_SERNO", "CREL$YEAR$$MONTH$$DAY$$SEQ$", 8);
	}

	/**
	 * @description:ok文件校验
	 * @param num
	 * @return
	 * @date:2019年1月25日 下午8:21:11
	 * @author:wangyk3
	 * @throws IOException
	 */
	public void okFileCheck(int num) throws IOException, Exception {
		logger.info("************************** 校验信号文件开始 **************************");
		/** 定义文件 **/
		File file = null;
		/** 定义文件流 **/
		InputStreamReader reader = null;
		/** 定义子字符串 **/
		BufferedReader br = null;
		/** 定义文件读取内容 **/
		String context = "";
		/** 定义信号文件记录数 **/
		int okNum = 0;
		/** 文件完整路径 **/
		String totalPath = null;
		try {
			/************************** 1.获取文件 **************************/
			/** 获取昨天的日期(因文件凌晨1点左右推送完成，此批次定时调度定在2点) **/
			LocalDate localdate = LocalDate.now().minusDays(1);
			/** 获取文件名称 **/
			filename = filename.replace("yyyyMMdd", localdate.format(DateTimeFormatter.ofPattern("yyyyMMdd")).toString());
			logger.info("读取信号文件名称：" + filename);
			/** 获取文件路径 **/
			totalPath = filePath + filename;
			logger.info("读取信号文件路径：" + filePath);

			/************************** 2.解析文件 **************************/
			/** 构建文件 **/
			file = new File(totalPath);
			/** 解析文件 **/
			if (file.isFile() && file.exists()) {
				/** 构建文件流 **/
				reader = new InputStreamReader(new FileInputStream(file), "utf-8");
				/** 读取文件 **/
				br = new BufferedReader(reader);
				context = br.readLine();
				if (context != null && !"".equals(context)) {
					/** 获取信号文件记录数 **/
					okNum = Integer.parseInt(context.substring(context.indexOf("=") + 1, context.length()));
					/** 检验信号文件 **/
					if (okNum == num) {
						logger.info("信号文件记录数与实际文件记录数检查正确,-- 信号文件记录数 ：" + okNum + "-- 实际文件记录数 :" + num);
					} else {
						logger.error("信号文件记录数与实际文件记录数不符合,-- 信号文件记录数 ：" + okNum + "-- 实际文件记录数 :" + num + "--请检查！");
						throw new BizException("信号文件记录数与实际文件记录数不符合,-- 信号文件记录数 ：" + okNum + "-- 实际文件记录数 :" + num + "--请检查！");
					}
				} else {
					logger.error("文件不存在或信号文件为空或首行格式错误,请检查！");
					throw new BizException("文件不存在或信号文件为空或首行格式错误,请检查！");
				}

			} else {
				logger.error("文件不存在,请检查！");
				throw new Exception("文件不存在,请检查！");
			}
		} catch (BizException e) {
			logger.error("文件读取错误,请检查！");
			e.printStackTrace();
			throw e;
		} catch (Exception e) {
			logger.error("文件读取错误,请检查！");
			e.printStackTrace();
			throw e;
		} finally {
			if (reader != null) {
				reader.close();
			}

			if (br != null) {
				br.close();
			}
			logger.info("************************** 校验信号文件结束 **************************");
		}
	}
}
